home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / sockuser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-10  |  9.6 KB  |  485 lines

  1. #include "global.h"
  2. #include "config.h"
  3. #ifdef    ANSIPROTO
  4. #include <stdarg.h>
  5. #endif
  6. #include <conio.h>
  7. #include "mbuf.h"
  8. #include "proc.h"
  9. #include "socket.h"
  10. #ifdef LZW
  11. #include "lzw.h"
  12. #endif
  13. #include "usock.h"
  14. #include "session.h"
  15. #include "nr4.h"
  16.  
  17. #ifdef SOBUF
  18. #undef SOBUF
  19. #endif
  20.  
  21. #define    SOBUF    768
  22.  
  23. /* Higher-level receive routine, intended for connection-oriented sockets.
  24.  * Can be used with datagram sockets, although the sender id is lost.
  25.  */
  26. int
  27. recv(s,buf,len,flags)
  28. int s;        /* Socket index */
  29. char *buf;    /* User buffer */
  30. int len;    /* Max length to receive */
  31. int flags;    /* Unused; will eventually select oob data, etc */
  32. {
  33.     struct mbuf *bp;
  34.     int cnt;
  35.  
  36.     if(len == 0)
  37.         return 0;    /* Otherwise would be interp as "all" */
  38.  
  39.     if((cnt = recv_mbuf(s,&bp,flags,NULLCHAR,(int *)NULL)) > 0) {
  40.         cnt = (int)min(cnt,len);
  41.         pullup(&bp,buf,(int16)cnt);
  42.         free_p(bp);
  43.     }
  44.     return cnt;
  45. }
  46. /* Higher level receive routine, intended for datagram sockets. Can also
  47.  * be used for connection-oriented sockets, although from and fromlen are
  48.  * ignored.
  49.  */
  50. int
  51. recvfrom(s,buf,len,flags,from,fromlen)
  52. int s;        /* Socket index */
  53. char *buf;    /* User buffer */
  54. int len;    /* Maximum length */
  55. int flags;    /* Unused; will eventually select oob data, etc */
  56. char *from;    /* Source address, only for datagrams */
  57. int *fromlen;    /* Length of source address */
  58. {
  59.     struct mbuf *bp;
  60.     int cnt;
  61.  
  62.     if((cnt = recv_mbuf(s,&bp,flags,from,fromlen)) > 0) {
  63.         cnt = (int)min(cnt,len);
  64.         pullup(&bp,buf,(int16)cnt);
  65.         free_p(bp);
  66.     }
  67.     return cnt;
  68. }
  69. /* High level send routine */
  70. int
  71. send(s,buf,len,flags)
  72. int s;        /* Socket index */
  73. char *buf;    /* User buffer */
  74. int len;    /* Length of buffer */
  75. int flags;    /* Unused; will eventually select oob data, etc */
  76. {
  77.     struct mbuf *bp;
  78.     char sock[MAXSOCKSIZE];
  79.     int i = MAXSOCKSIZE;
  80.  
  81.     if(getpeername(s,sock,&i) == -1)
  82.         return -1;
  83.     bp = qdata(buf,(int16)len);
  84.     return send_mbuf(s,bp,flags,sock,i);
  85. }
  86. /* High level send routine, intended for datagram sockets. Can be used on
  87.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  88.  */
  89. int
  90. sendto(s,buf,len,flags,to,tolen)
  91. int s;        /* Socket index */
  92. char *buf;    /* User buffer */
  93. int len;    /* Length of buffer */
  94. int flags;    /* Unused; will eventually select oob data, etc */
  95. char *to;    /* Destination, only for datagrams */
  96. int tolen;    /* Length of destination */
  97. {
  98.     struct mbuf *bp;
  99.  
  100.     bp = qdata(buf,(int16)len);
  101.     return send_mbuf(s,bp,flags,to,tolen);
  102. }
  103. /* Receive a newline-terminated line from a socket, returning # chars read.
  104.  * The end-of-line sequence is recognized and translated into a single '\n'.
  105.  */
  106. int
  107. recvline(s,buf,len)
  108. int s;        /* Socket index */
  109. char *buf;    /* User buffer */
  110. unsigned len;    /* Length of buffer */
  111. {
  112.     int c, cnt = 0;
  113.  
  114.     while(len-- > 1){
  115.         if((c = recvchar(s)) == EOF){
  116.             cnt = -1;
  117.             break;
  118.         }
  119.         if(buf != NULLCHAR)
  120.             *buf++ = c;
  121.         cnt++;
  122.         if(uchar(c) == '\n')
  123.             break;
  124.     }
  125.     if(buf != NULLCHAR)
  126.         *buf = '\0';
  127.     return cnt;
  128. }
  129. #if    defined(ANSIPROTO)
  130. /* Do printf on a user socket */
  131. int
  132. usprintf(int s,char *fmt,...)
  133. {
  134.     va_list args;
  135.     int len;
  136.  
  137.     va_start(args,fmt);
  138.     len = usvprintf(s,fmt,args);
  139.     va_end(args);
  140.     return len;
  141. }
  142. /* Printf on standard output socket */
  143. int
  144. tprintf(char *fmt,...)
  145. {
  146.     va_list args;
  147.     int len;
  148.  
  149.     va_start(args,fmt);
  150.     len = usvprintf(Curproc->output,fmt,args);
  151.     va_end(args);
  152.     return len;
  153. }
  154. /* The guts of printf, uses variable arg version of sprintf */
  155. int
  156. usvprintf(int s,char *fmt, va_list args)
  157. {
  158.     int i, len;
  159.     register char *cp, buf[SOBUF];
  160.  
  161.     if(strchr(fmt,'%') == NULLCHAR){
  162.         /* No args, so we don't need vsprintf() */
  163.         len = strlen(fmt);
  164.         cp = fmt;
  165.     } else {
  166.         /* Use a default value that is hopefully longer than the
  167.          * biggest output string we'll ever print (!)
  168.          */
  169.         vsprintf(buf,fmt,args);
  170.         len = strlen(buf);
  171.         cp = buf;
  172.     }
  173.     i = len;
  174.     while(i-- > 0) {
  175.         if(usputc(s,*cp++) == EOF) {
  176.             return EOF;
  177.         }
  178.     }
  179.     return len;
  180. }
  181. #else
  182. /*VARARGS*/
  183. /* Printf to standard output socket */
  184. int
  185. tprintf(fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  186. char *fmt;        /* Message format */
  187. int arg1,arg2,arg3;    /* Arguments */
  188. int arg4,arg5,arg6;
  189. int arg7,arg8,arg9;
  190. int arg10,arg11,arg12;
  191. {
  192.     return usprintf(Curproc->output,fmt,arg1,arg2,arg3,arg4,arg5,arg6,
  193.         arg7,arg8,arg9,arg10,arg11,arg12);
  194. }
  195. /* Printf to socket. Doesn't use ANSI vsprintf */
  196. int
  197. usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  198. int s;            /* Socket index */
  199. char *fmt;        /* Message format */
  200. int arg1,arg2,arg3;    /* Arguments */
  201. int arg4,arg5,arg6;
  202. int arg7,arg8,arg9;
  203. int arg10,arg11,arg12;
  204. {
  205.     int i, len;
  206.     register char *cp;
  207.  
  208.     if(strchr(fmt,'%') == NULLCHAR){
  209.         /* No args, so we don't need vsprintf() */
  210.         char *buf1 = fmt;
  211.         len = strlen(buf1);
  212.         cp = buf1;
  213.     } else {
  214.         /* Use a default value that is hopefully longer than the
  215.          * biggest output string we'll ever print (!)
  216.          */
  217.         char buf[SOBUF];
  218.         sprintf(buf,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,
  219.          arg8,arg9,arg10,arg11,arg12);
  220.         len = strlen(buf);
  221.         cp = buf;
  222.     }
  223.     i = len;
  224.     while(i-- > 0) {
  225.         if(usputc(s,*cp++) == -1) {
  226.             len = -1;
  227.             break;
  228.         }
  229.     }
  230.     return len;
  231. }
  232. #endif
  233.  
  234. /* Buffered putchar to a socket */
  235. int
  236. usputc(s,c)
  237. int s;
  238. char c;
  239. {
  240.     register struct usock *up;
  241.     struct mbuf *bp;
  242.     char *cp;
  243.  
  244.     if((up = itop(s)) == NULLUSOCK){
  245.         errno = EBADF;
  246.         return -1;
  247.     }
  248.     if(up->obuf == NULLBUF){
  249.         /* Allocate a buffer of appropriate size */
  250.         switch(up->type){
  251. #ifdef NETROM
  252.         case TYPE_NETROML4:
  253.             up->obuf = ambufw(Nr_iface->mtu);
  254.             break;
  255. #endif
  256.         default:
  257.             up->obuf = ambufw(BUFSIZ);
  258.             break;
  259.         }
  260.     }
  261.     bp = up->obuf;
  262.     if(c == '\n' && (up->flag & SOCK_ASCII)){
  263.         /* Translate into appropriate end-of-line sequence */
  264.         for(cp = up->eol;*cp != '\0';cp++)
  265. #ifdef LZW
  266.             if(up->zout == NULLLZW)
  267. #endif
  268.                 bp->data[bp->cnt++] = *cp;
  269. #ifdef LZW
  270.             else
  271.                 lzwencode(s,*cp);
  272. #endif
  273.     } else {
  274. #ifdef LZW
  275.         if(up->zout == NULLLZW)
  276. #endif
  277.             bp->data[bp->cnt++] = c;
  278. #ifdef LZW
  279.         else
  280.             lzwencode(s,c);
  281. #endif
  282.     }
  283.     /* Always leave enough room for an eol sequence in the next call */
  284.     if((c == up->flush && up->flush != -1) || bp->cnt >= bp->size-9)
  285.         if(usflush(s) == EOF)
  286.             return EOF;
  287.  
  288.     return (int)uchar(c);
  289. }
  290.  
  291. /* Put a character to standard output socket */
  292. int
  293. tputc(c)
  294. char c;
  295. {
  296.     return usputc(Curproc->output,c);
  297. }
  298.  
  299. int
  300. usputs(s,x)
  301. int s;
  302. char *x;
  303. {
  304.     while(*x != '\0')
  305.         if(usputc(s,*x++) == EOF)
  306.             return EOF;
  307.     return 0;
  308. }
  309.  
  310. /* Put a string to standard output socket */
  311. int
  312. tputs(s)
  313. char *s;
  314. {
  315.     while(*s != '\0')
  316.         if(usputc(Curproc->output,*s++) == EOF)
  317.             return EOF;
  318.     return 0;
  319. }
  320.  
  321. /* Read a raw character from a socket with stream buffering. */
  322. int
  323. rrecvchar(s)
  324. int s;            /* Socket index */
  325. {
  326.     register struct usock *up;
  327. #ifdef LZW
  328.     int c;
  329. #endif
  330.  
  331.     if((up = itop(s)) == NULLUSOCK)
  332.         return EOF;
  333. #ifdef LZW
  334.     if(up->zin != NULLLZW && (c = lzwdecode(up)) != -1)
  335.         return c;
  336. #endif
  337.     /* Replenish if necessary */
  338.     if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0)
  339.         return EOF;
  340. #ifdef LZW
  341.     if(up->zin != NULLLZW)
  342.         if((c = lzwdecode(up)) != -1)
  343.             return c;
  344.         else
  345.             return rrecvchar(s);    /* need to replenish */
  346. #endif
  347.     return PULLCHAR(&up->ibuf);    /* Returns -1 if eof */
  348. }
  349. /* This function recognizes the end-of-line sequence for the stream
  350.  * and translates it into a single '\n'.
  351.  */
  352. int
  353. recvchar(s)
  354. int s;            /* Socket index */
  355. {
  356.     register struct usock *up;
  357.     int c;
  358.  
  359.     if((up = itop(s)) == NULLUSOCK)
  360.         return EOF;
  361.  
  362.     c = rrecvchar(s);
  363.  
  364.     if(c != up->eol[0] || !(up->flag & SOCK_ASCII))
  365.         return c;
  366.  
  367.     /* This is the first char of a eol sequence. If the eol sequence is
  368.      * more than one char long, eat the next character in the input stream.
  369.      */
  370.     if(up->eol[1] != '\0'){
  371.         (void)rrecvchar(s);
  372.     }
  373.     return '\n';
  374. }
  375. /* Flush output on a socket stream */
  376. int
  377. usflush(s)
  378. int s;
  379. {
  380.     struct usock *up;
  381.     struct mbuf *bp;
  382.  
  383.     if((up = itop(s)) == NULLUSOCK)
  384.         return -1;
  385.  
  386.     if(up->obuf != NULLBUF){
  387. #ifdef LZW
  388.         if(up->zout != NULLLZW)
  389.             lzwflush(up);
  390. #endif
  391.         bp = up->obuf;
  392.         up->obuf = NULLBUF;
  393.         return send_mbuf(s,bp,0,NULLCHAR,0);
  394.     }
  395.     return 0;
  396. }
  397.  
  398. /* Flush output socket */
  399. void
  400. tflush()
  401. {
  402.     usflush(Current->output);
  403. }
  404.  
  405. /* Print prompt and read one character */
  406. int
  407. keywait(prompt,flush)
  408. char *prompt;    /* Optional prompt */
  409. int flush;    /* Flush queued input? */
  410. {
  411.     int c, i;
  412.  
  413.     if(flush && socklen(Curproc->input,1) != 0)
  414.         recv_mbuf(Curproc->input,NULLBUFP,0,NULLCHAR,0); /* flush */
  415.     if(prompt == NULLCHAR)
  416.         prompt = "Hit enter to continue";
  417.     tputs(prompt);
  418.     tflush();
  419.     c = recvchar(Curproc->input);
  420.     /* Get rid of the prompt */
  421.     for(i = strlen(prompt); i != 0; i--)
  422.         tputs("\b \b");
  423.     tflush();
  424.     return (int)c;
  425. }
  426.  
  427. /* Set the end-of-line sequence on a socket */
  428. int
  429. seteol(s,seq)
  430. int s;
  431. char *seq;
  432. {
  433.     struct usock *up;
  434.  
  435.     if((up = itop(s)) == NULLUSOCK)
  436.         return -1;
  437.  
  438.     if(seq != NULLCHAR)
  439.         strncpy(up->eol,seq,sizeof(up->eol));
  440.     else
  441.         *up->eol = '\0';
  442.     return 0;
  443. }
  444. /* Enable/disable eol translation, return previous state */
  445. int
  446. sockmode(s,mode)
  447. int s,mode;
  448. {
  449.     struct usock *up;
  450.     int prev;
  451.  
  452.     if((up = itop(s)) == NULLUSOCK)
  453.         return -1;
  454.     usflush(s);
  455.     prev = up->flag;
  456.     switch(mode){
  457.     case SOCK_BINARY:
  458.     case SOCK_ASCII:
  459.         up->flag = mode;
  460.         break;
  461.     default:
  462.         break;
  463.     }
  464.     return prev;
  465. }
  466. /* Specify the character to trigger automatic output buffer
  467.  * flushing, or -1 to disable it. Return the previous setting.
  468.  */
  469. int
  470. setflush(s,c)
  471. int s;
  472. int c;
  473. {
  474.     struct usock *up;
  475.     int old;
  476.  
  477.     if((up = itop(s)) == NULLUSOCK)
  478.         return -1;
  479.  
  480.     old = up->flush;
  481.     up->flush = c;
  482.     return old;
  483. }
  484.  
  485.